import { IPageResponse } from "../../types/CommonType";
import { ValidationError } from "../../utils/errors";
import { getTreeStructure, readExcel, removeFile } from "../../utils/tools";
import CatModel from "../../dao/model/pet/CatModel";
import CatEntity, { ICatModel, importFieldMap } from "../../entities/pet/CatEntity";
import { Op } from "sequelize";
import { handleImportImage } from "../../utils/extractExcelImg";
import CatteryModel from "../../dao/model/pet/CatteryModel";

export enum sexMap {
  "公" = "1",
  "母" = "2",
}
export enum hairMap {
  "长" = "1",
  "短" = "2",
}

export class CatService {
  /**
   * 添加数据
   */
  public static async add(admin: CatEntity): Promise<true> {
    // 1. 转换类型
    admin = CatEntity.transform(admin);
    // 2. 数据验证
    const errors = await admin.validateThis();
    if (errors.length > 0) {
      throw new ValidationError(errors[0]);
    }

    await CatModel.create<ICatModel>(admin);
    return true;
  }

  /**
   * 分页获取数据
   */
  public static async findByPage(offset: number, limit: number, where?): Promise<IPageResponse> {
    if (where.name) {
      where.name = {
        [Op.like]: `%${where.name}%`,
      };
    }

    let data = await CatModel.findAndCountAll<ICatModel>({
      offset: limit * (offset - 1),
      limit,
      where,
    });

    const result: IPageResponse = {
      total: data.count,
      list: data.rows.map((item) => item.dataValues),
    };

    return result;
  }

  public static async findByList(where: any = {}, _token: any) {
    if (where?.name) {
      where.name = {
        [Op.like]: `%${where.name}%`,
      };
    }
    if (where?.chipCode) {
      where.chipCode = {
        [Op.like]: `%${where.chipCode}%`,
      };
    }
    return CatModel.findAll<ICatModel>({ where });
  }

  public static async findByTreeList(where: any = {}) {
    const result = await CatModel.findAll<ICatModel>({ where });

    return getTreeStructure<CatEntity>(result.map((item) => item.dataValues));
  }

  /**
   * 通过id获取数据
   */
  public static async findById(id: string) {
    return CatModel.findByPk<ICatModel>(id);
  }

  /**
   * 修改数据
   */
  public static async update(data: any) {
    return CatModel.update<ICatModel>(data, {
      where: {
        id: data.id,
      },
    });
  }

  /**
   * 删除数据
   */
  public static async delete(id: string) {
    return CatModel.destroy({
      where: {
        id,
      },
    });
  }

  public static async importData(filePath: string, petType) {
    const rows: any = readExcel(filePath);
    let data: any = [];

    const cache = {};

    for (const item of rows) {
      const keys = Object.keys(item);
      const obj: any = {};
      keys.forEach((key) => {
        obj[importFieldMap[key]] = item[key];
      });

      // 字段默认值
      obj.petStatus = "1";
      obj.petType = petType;

      if (obj.catteryId) {
        // 处理猫舍
        if (cache[obj.catteryId]) {
          obj.catteryId = cache[obj.catteryId]
        } else {
          let cattery = await CatteryModel.findOne({
            where: {
              name: obj.catteryId
            }
          })
          if (!cattery || !cattery.dataValues) {
            cattery = await CatteryModel.create({ name: obj.catteryId })
          }
          cache[obj.catteryId] = cattery.dataValues.id
          obj.catteryId = cattery.dataValues.id
        }
      } else {
        delete item.catteryId
      }
      data.push(obj);
    }

    // 处理图片
    data = await handleImportImage(filePath, data);

    /**
     * 字典映射
     */
    for (const item of data) {
      item.sex = sexMap[item.sex];
      item.hair = hairMap[item.hair];
    }

    const result: any = [];
    for (let item of data) {
      item = CatEntity.transform(item);
      // 2. 数据验证
      const errors = await item.validateThis();
      if (errors.length === 0) {
        result.push(item);
      }
    }
    await CatModel.bulkCreate(result);
    removeFile(filePath);
    return result.length;
  }

  public static async getAllHome() {
    const rows = await CatModel.findAll<ICatModel>();
    const data = rows
      .map((item) => ({ name: item.dataValues.homeName, petType: item.dataValues.petType }))
      .filter((item) => item.name);

    // 去重
    const result: any = [];
    for (const item of data) {
      if (!result.some((res: any) => res.name === item.name)) {
        result.push(item);
      }
    }
    return result;
  }
}
